/**
 *    Copyright (C) 2008, 2009  Victor Smirnov <aist11@gmail.com>
 *
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License along
 *    with this program; if not, write to the Free Software Foundation, Inc.,
 *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 *    See LICENSE.exceptions in the root folder of this project for possible
 *    exceptions
 *
 */

#ifndef _CUBEFS_API_REFLECTION_BASIC_TYPED_OPERATION_HPP
#define	_CUBEFS_API_REFLECTION_BASIC_TYPED_OPERATION_HPP

#include <cubefs/api/reflection/operation.hpp>
#include <cubefs/core/api/reflection/operation.hpp>

#include <vector>



#define CUBEFS_SOURCE "cubefs/core/api/reflection/basic_typed_operation.hpp:" CUBEFS_AT

namespace cubefs    {
namespace api       {


template <typename T, Int ArgsNum>
class TypedOperationImpl: public AbstractOperationImpl<ArgsNum> {

    typedef AbstractOperationImpl<ArgsNum> Base;

public:
    TypedOperationImpl(Type *owner, StringRef name, Operation *op, bool static0 = false):
        Base(owner, TypeFactory<T>::type(), name, static0) {
        }

    virtual Typed *invoke(Typed* target, StaticListOfTyped* arguments) const {
        return TypedWrapperFactory<T>::create(this->invokeTyped(target, arguments));
    }

    virtual T invokeTyped(Typed* target, StaticListOfTyped* arguments) const = 0;
};


template <Int ArgsNum>
class TypedOperationImpl<void, ArgsNum>: public AbstractOperationImpl<ArgsNum> {

    typedef AbstractOperationImpl<ArgsNum> Base;

public:
    TypedOperationImpl(Type *owner, StringRef name, Operation *op, bool static0 = false):
        Base(owner, TypeFactory<void>::type(), name, static0) {}


    virtual Typed *invoke(Typed* target, StaticListOfTyped* arguments) const {
    	this->invokeTyped(target, arguments);
        return NULL;
    }

    virtual void invokeTyped(Typed* target, StaticListOfTyped* arguments) const = 0;
};



template <typename RtnType, typename Functor>
class BasicStaticOperation<RtnType (*)(), Functor>: public TypedOperationImpl<RtnType, 0> {
    typedef TypedOperationImpl<RtnType, 0> Base;

    Functor functor_;

public:
    BasicStaticOperation(Type *owner, const std::string name, Functor functor):
        Base(owner, name, this, true),
        functor_(functor) {}

    virtual RtnType invokeTyped(Typed* target, StaticListOfTyped* arguments) const {
        return (*functor_)();
    }
};

template <typename RtnType, typename Target, typename Functor>
class BasicOperation<RtnType (Target::*)(), Functor>: public TypedOperationImpl<RtnType, 0> {
    typedef TypedOperationImpl<RtnType, 0> Base;

    Functor functor_;

public:
    BasicOperation(Type *owner, const std::string name, Functor functor):
        Base(owner, name, this), functor_(functor) {}

    virtual RtnType invokeTyped(Typed* target, StaticListOfTyped* arguments) const {
        Base::CheckTargetValue(target);
        Target* tgt = static_cast<Target*>(target);
        return (tgt->*functor_)();
    }
};


template <typename RtnType, typename T1, typename Functor>
class BasicStaticOperation<RtnType (*)(T1), Functor>: public TypedOperationImpl<RtnType, 1> {
    typedef TypedOperationImpl<RtnType, 1> Base;
    Functor functor_;

public:
    BasicStaticOperation(Type *owner, const std::string &name, const std::string &p0_name, Functor functor):
        Base(owner, name, this, true),
        functor_(functor)
    {
        Type* p0_type = TypeFactory<T1>::type();
        Base::AddArgumentType(new ArgumentImpl(p0_name, p0_type));
    }

    virtual RtnType invokeTyped(Typed* target, StaticListOfTyped* arguments) const {
        Base::CheckArgumentTypes(arguments);
        T1 t1 = ParameterTypeHelper<T1>::convert(arguments->Get(0));
        return (*functor_)(t1);
    }
};

template <typename RtnType, typename Target, typename T1, typename Functor>
class BasicOperation<RtnType (Target::*)(T1), Functor>: public TypedOperationImpl<RtnType, 1> {
    typedef TypedOperationImpl<RtnType, 1> Base;

    Functor functor_;

public:
    BasicOperation(Type *owner, const std::string &name, const std::string &p0_name, Functor functor):
        Base(owner, name, this),
        functor_(functor)
    {
        Type* p0_type = TypeFactory<T1>::type();
        Base::AddArgumentType(new ArgumentImpl(p0_name, p0_type));
    }

    virtual RtnType invokeTyped(Typed* target, StaticListOfTyped* arguments) const {
        Base::CheckTargetValue(target);
        Base::CheckArgumentTypes(arguments);

        Target* tgt = static_cast<Target*>(target);

        T1 t1 = ParameterTypeHelper<T1>::convert(arguments->Get(0));

        return (tgt->*functor_)(t1);
    }
};




template <typename RtnType, typename T1, typename T2, typename Functor>
class BasicStaticOperation<RtnType (*)(T1, T2), Functor>: public TypedOperationImpl<RtnType, 2> {
    typedef TypedOperationImpl<RtnType, 2> Base;

    Functor functor_;

public:
    BasicStaticOperation(
            Type *owner,
            const std::string &name,
            const std::string &p0_name,
            const std::string &p1_name,
            Functor functor
    ):
        Base(owner, name, this, true),
        functor_(functor)
    {
        Type* p0_type = TypeFactory<T1>::type();
        Type* p1_type = TypeFactory<T2>::type();

        Base::AddArgumentType(new ArgumentImpl(p0_name, p0_type));
        Base::AddArgumentType(new ArgumentImpl(p1_name, p1_type));
    }

    virtual RtnType invokeTyped(Typed* target, StaticListOfTyped* arguments) const {
        Base::CheckArgumentTypes(arguments);
        T1 t1 = ParameterTypeHelper<T1>::convert(arguments->Get(0));
        T2 t2 = ParameterTypeHelper<T2>::convert(arguments->Get(1));
        return (*functor_)(t1, t2);
    }
};

template <typename RtnType, typename Target, typename T1, typename T2, typename Functor>
class BasicOperation<RtnType (Target::*)(T1, T2), Functor>: public TypedOperationImpl<RtnType, 2> {
    typedef TypedOperationImpl<RtnType, 2> Base;

    Functor functor_;

public:
    BasicOperation(
            Type *owner,
            const std::string &name,
            const std::string &p0_name,
            const std::string &p1_name,
            Functor functor
    ):
        Base(owner, name, this),
        functor_(functor)
    {
        Type* p0_type = TypeFactory<T1>::type();
        Type* p1_type = TypeFactory<T2>::type();

        Base::AddArgumentType(new ArgumentImpl(p0_name, p0_type));
        Base::AddArgumentType(new ArgumentImpl(p1_name, p1_type));
    }

    virtual RtnType invokeTyped(Typed* target, StaticListOfTyped* arguments) const {
        Base::CheckTargetValue(target);
        Base::CheckArgumentTypes(arguments);

        Target* tgt = static_cast<Target*>(target);

        T1 t1 = ParameterTypeHelper<T1>::convert(arguments->Get(0));
        T2 t2 = ParameterTypeHelper<T2>::convert(arguments->Get(1));

        return (tgt->*functor_)(t1, t2);
    }
};




template <typename RtnType, typename T1, typename T2, typename T3, typename Functor>
class BasicStaticOperation<RtnType (*)(T1, T2, T3), Functor>: public TypedOperationImpl<RtnType, 3> {
    typedef TypedOperationImpl<RtnType, 3> Base;

    Functor functor_;

public:
    BasicStaticOperation(
            Type *owner,
            const std::string &name,
            const std::string &p0_name,
            const std::string &p1_name,
            const std::string &p2_name,
            Functor functor
    ):
        Base(owner, name, this, true),
        functor_(functor)
    {
        Type* p0_type = TypeFactory<T1>::type();
        Type* p1_type = TypeFactory<T2>::type();
        Type* p2_type = TypeFactory<T3>::type();

        Base::AddArgumentType(new ArgumentImpl(p0_name, p0_type));
        Base::AddArgumentType(new ArgumentImpl(p1_name, p1_type));
        Base::AddArgumentType(new ArgumentImpl(p2_name, p2_type));
    }

    virtual RtnType invokeTyped(Typed* target, StaticListOfTyped* arguments) const {
        Base::CheckArgumentTypes(arguments);
        T1 t1 = ParameterTypeHelper<T1>::convert(arguments->Get(0));
        T2 t2 = ParameterTypeHelper<T2>::convert(arguments->Get(1));
        T3 t3 = ParameterTypeHelper<T3>::convert(arguments->Get(2));
        return (*functor_)(t1, t2, t3);
    }
};

template <typename RtnType, typename Target, typename T1, typename T2, typename T3, typename Functor>
class BasicOperation<RtnType (Target::*)(T1, T2, T3), Functor>: public TypedOperationImpl<RtnType, 3> {
    typedef TypedOperationImpl<RtnType, 3> Base;

    Functor functor_;

public:
    BasicOperation(
            Type *owner,
            const std::string &name,
            const std::string &p0_name,
            const std::string &p1_name,
            const std::string &p2_name,
            Functor functor
    ):
        Base(owner, name, this),
        functor_(functor)
    {
        Type* p0_type = TypeFactory<T1>::type();
        Type* p1_type = TypeFactory<T2>::type();
        Type* p2_type = TypeFactory<T3>::type();

        Base::AddArgumentType(new ArgumentImpl(p0_name, p0_type));
        Base::AddArgumentType(new ArgumentImpl(p1_name, p1_type));
        Base::AddArgumentType(new ArgumentImpl(p2_name, p2_type));
    }

    virtual RtnType invokeTyped(Typed* target, StaticListOfTyped* arguments) const {
        Base::CheckTargetValue(target);
        Base::CheckArgumentTypes(arguments);

        Target* tgt = static_cast<Target*>(target);

        T1 t1 = ParameterTypeHelper<T1>::convert(arguments->Get(0));
        T2 t2 = ParameterTypeHelper<T2>::convert(arguments->Get(1));
        T3 t3 = ParameterTypeHelper<T3>::convert(arguments->Get(2));

        return (tgt->*functor_)(t1, t2, t3);
    }
};




template <typename RtnType, typename T1, typename T2, typename T3, typename T4, typename Functor>
class BasicStaticOperation<RtnType (*)(T1, T2, T3, T4), Functor>: public TypedOperationImpl<RtnType, 4> {
    typedef TypedOperationImpl<RtnType, 4> Base;

    Functor functor_;

public:
    BasicStaticOperation(
            Type *owner,
            const std::string &name,
            const std::string &p0_name,
            const std::string &p1_name,
            const std::string &p2_name,
            const std::string &p3_name,
            Functor functor
    ):
        Base(owner, name, this, true),
        functor_(functor)
    {
        Type* p0_type = TypeFactory<T1>::type();
        Type* p1_type = TypeFactory<T2>::type();
        Type* p2_type = TypeFactory<T3>::type();
        Type* p3_type = TypeFactory<T4>::type();

        Base::AddArgumentType(new ArgumentImpl(p0_name, p0_type));
        Base::AddArgumentType(new ArgumentImpl(p1_name, p1_type));
        Base::AddArgumentType(new ArgumentImpl(p2_name, p2_type));
        Base::AddArgumentType(new ArgumentImpl(p3_name, p3_type));
    }

    virtual RtnType invokeTyped(Typed* target, StaticListOfTyped* arguments) const {
        Base::CheckArgumentTypes(arguments);
        T1 t1 = ParameterTypeHelper<T1>::convert(arguments->Get(0));
        T2 t2 = ParameterTypeHelper<T2>::convert(arguments->Get(1));
        T3 t3 = ParameterTypeHelper<T3>::convert(arguments->Get(2));
        T4 t4 = ParameterTypeHelper<T4>::convert(arguments->Get(3));
        return (*functor_)(t1, t2, t3, t4);
    }
};

template <typename RtnType, typename Target, typename T1, typename T2, typename T3, typename T4, typename Functor>
class BasicOperation<RtnType (Target::*)(T1, T2, T3, T4), Functor>: public TypedOperationImpl<RtnType, 4> {
    typedef TypedOperationImpl<RtnType, 4> Base;

    Functor functor_;

public:
    BasicOperation(
            Type *owner,
            const std::string &name,
            const std::string &p0_name,
            const std::string &p1_name,
            const std::string &p2_name,
            const std::string &p3_name,
            Functor functor
    ):
        Base(owner, name, this),
        functor_(functor)
    {
        Type* p0_type = TypeFactory<T1>::type();
        Type* p1_type = TypeFactory<T2>::type();
        Type* p2_type = TypeFactory<T3>::type();
        Type* p3_type = TypeFactory<T4>::type();

        Base::AddArgumentType(new ArgumentImpl(p0_name, p0_type));
        Base::AddArgumentType(new ArgumentImpl(p1_name, p1_type));
        Base::AddArgumentType(new ArgumentImpl(p2_name, p2_type));
        Base::AddArgumentType(new ArgumentImpl(p3_name, p3_type));
    }

    virtual RtnType invokeTyped(Typed* target, StaticListOfTyped* arguments) const {
        Base::CheckTargetValue(target);
        Base::CheckArgumentTypes(arguments);

        Target* tgt = static_cast<Target*>(target);

        T1 t1 = ParameterTypeHelper<T1>::convert(arguments->Get(0));
        T2 t2 = ParameterTypeHelper<T2>::convert(arguments->Get(1));
        T3 t3 = ParameterTypeHelper<T3>::convert(arguments->Get(2));
        T4 t4 = ParameterTypeHelper<T4>::convert(arguments->Get(3));

        return (tgt->*functor_)(t1, t2, t3, t4);
    }
};





template <typename Functor>
class BasicStaticOperation<void (*)(), Functor>: public TypedOperationImpl<void, 0> {
    typedef TypedOperationImpl<void, 0> Base;

    Functor functor_;

public:
    BasicStaticOperation(Type *owner, const std::string name, Functor functor):
        Base(owner, name, this, true),
        functor_(functor)
    {}

    virtual void invokeTyped(Typed* target, StaticListOfTyped* arguments) const
    {
        (*functor_)();
    }
};

template <typename Target, typename Functor>
class BasicOperation<void (Target::*)(), Functor>: public TypedOperationImpl<void, 0> {
    typedef TypedOperationImpl<void, 0> Base;

    Functor functor_;

public:
    BasicOperation(Type *owner, const std::string name, Functor functor):
        Base(owner, name, this), functor_(functor) {}

    virtual void invokeTyped(Typed* target, StaticListOfTyped* arguments) const {
        Base::CheckTargetValue(target);
        Target* tgt = static_cast<Target*>(target);
        (tgt->*functor_)();
    }
};


template <typename T1, typename Functor>
class BasicStaticOperation<void (*)(T1), Functor>: public TypedOperationImpl<void, 1> {
    typedef TypedOperationImpl<void, 1> Base;
    Functor functor_;

public:
    BasicStaticOperation(Type *owner, const std::string &name, const std::string &p0_name, Functor functor):
        Base(owner, name, this, true),
        functor_(functor)
    {
        Type* p0_type = TypeFactory<T1>::type();
        Base::AddArgumentType(new ArgumentImpl(p0_name, p0_type));
    }

    virtual void invokeTyped(Typed* target, StaticListOfTyped* arguments) const {
    	Base::CheckArgumentTypes(arguments);
        T1 t1 = ParameterTypeHelper<T1>::convert(arguments->Get(0));
        (*functor_)(t1);
    }
};

template <typename Target, typename T1, typename Functor>
class BasicOperation<void (Target::*)(T1), Functor>: public TypedOperationImpl<void, 1> {
    typedef TypedOperationImpl<void, 1> Base;

    Functor functor_;

public:
    BasicOperation(Type *owner, const std::string &name, const std::string &p0_name, Functor functor):
        Base(owner, name, this),
        functor_(functor)
    {
        Type* p0_type = TypeFactory<T1>::type();
        Base::AddArgumentType(new ArgumentImpl(p0_name, p0_type));
    }

    virtual void invokeTyped(Typed* target, StaticListOfTyped* arguments) const {
    	Base::CheckTargetValue(target);
        Base::CheckArgumentTypes(arguments);

        Target* tgt = static_cast<Target*>(target);
        T1 t1 = ParameterTypeHelper<T1>::convert(arguments->Get(0));

        (tgt->*functor_)(t1);
    }
};




template <typename T1, typename T2, typename Functor>
class BasicStaticOperation<void (*)(T1, T2), Functor>: public TypedOperationImpl<void, 2> {
    typedef TypedOperationImpl<void, 2> Base;

    Functor functor_;

public:
    BasicStaticOperation(
            Type *owner,
            const std::string &name,
            const std::string &p0_name,
            const std::string &p1_name,
            Functor functor
    ):
        Base(owner, name, this, true),
        functor_(functor)
    {
        Type* p0_type = TypeFactory<T1>::type();
        Type* p1_type = TypeFactory<T2>::type();

        Base::AddArgumentType(new ArgumentImpl(p0_name, p0_type));
        Base::AddArgumentType(new ArgumentImpl(p1_name, p1_type));
    }

    virtual void invokeTyped(Typed* target, StaticListOfTyped* arguments) const {
        Base::CheckArgumentTypes(arguments);
        T1 t1 = ParameterTypeHelper<T1>::convert(arguments->Get(0));
        T2 t2 = ParameterTypeHelper<T2>::convert(arguments->Get(1));
        (*functor_)(t1, t2);
    }
};

template <typename Target, typename T1, typename T2, typename Functor>
class BasicOperation<void (Target::*)(T1, T2), Functor>: public TypedOperationImpl<void, 2> {
    typedef TypedOperationImpl<void, 2> Base;

    Functor functor_;

public:
    BasicOperation(
            Type *owner,
            const std::string &name,
            const std::string &p0_name,
            const std::string &p1_name,
            Functor functor
    ):
        Base(owner, name, this),
        functor_(functor)
    {
        Type* p0_type = TypeFactory<T1>::type();
        Type* p1_type = TypeFactory<T2>::type();

        Base::AddArgumentType(new ArgumentImpl(p0_name, p0_type));
        Base::AddArgumentType(new ArgumentImpl(p1_name, p1_type));
    }

    virtual void invokeTyped(Typed* target, StaticListOfTyped* arguments) const {
        Base::CheckTargetValue(target);
        Base::CheckArgumentTypes(arguments);

        Target* tgt = static_cast<Target*>(target);

        T1 t1 = ParameterTypeHelper<T1>::convert(arguments->Get(0));
        T2 t2 = ParameterTypeHelper<T2>::convert(arguments->Get(1));

        return (tgt->*functor_)(t1, t2);
    }
};




template <typename T1, typename T2, typename T3, typename Functor>
class BasicStaticOperation<void (*)(T1, T2, T3), Functor>: public TypedOperationImpl<void, 3> {
    typedef TypedOperationImpl<void, 3> Base;

    Functor functor_;

public:
    BasicStaticOperation(
            Type *owner,
            const std::string &name,
            const std::string &p0_name,
            const std::string &p1_name,
            const std::string &p2_name,
            Functor functor
    ):
        Base(owner, name, this, true),
        functor_(functor)
    {
        Type* p0_type = TypeFactory<T1>::type();
        Type* p1_type = TypeFactory<T2>::type();
        Type* p2_type = TypeFactory<T3>::type();

        Base::AddArgumentType(new ArgumentImpl(p0_name, p0_type));
        Base::AddArgumentType(new ArgumentImpl(p1_name, p1_type));
        Base::AddArgumentType(new ArgumentImpl(p2_name, p2_type));
    }

    virtual void invokeTyped(Typed* target, StaticListOfTyped* arguments) const {
        Base::CheckArgumentTypes(arguments);
        T1 t1 = ParameterTypeHelper<T1>::convert(arguments->Get(0));
        T2 t2 = ParameterTypeHelper<T2>::convert(arguments->Get(1));
        T3 t3 = ParameterTypeHelper<T3>::convert(arguments->Get(2));
        return (*functor_)(t1, t2, t3);
    }
};

template <typename Target, typename T1, typename T2, typename T3, typename Functor>
class BasicOperation<void (Target::*)(T1, T2, T3), Functor>: public TypedOperationImpl<void, 3> {
    typedef TypedOperationImpl<void, 3> Base;

    Functor functor_;

public:
    BasicOperation(
            Type *owner,
            const std::string &name,
            const std::string &p0_name,
            const std::string &p1_name,
            const std::string &p2_name,
            Functor functor
    ):
        Base(owner, name, this),
        functor_(functor)
    {
        Type* p0_type = TypeFactory<T1>::type();
        Type* p1_type = TypeFactory<T2>::type();
        Type* p2_type = TypeFactory<T3>::type();

        Base::AddArgumentType(new ArgumentImpl(p0_name, p0_type));
        Base::AddArgumentType(new ArgumentImpl(p1_name, p1_type));
        Base::AddArgumentType(new ArgumentImpl(p2_name, p2_type));
    }

    virtual void invokeTyped(Typed* target, StaticListOfTyped* arguments) const {
        Base::CheckTargetValue(target);
        Base::CheckArgumentTypes(arguments);

        Target* tgt = static_cast<Target*>(target);

        T1 t1 = ParameterTypeHelper<T1>::convert(arguments->Get(0));
        T2 t2 = ParameterTypeHelper<T2>::convert(arguments->Get(1));
        T3 t3 = ParameterTypeHelper<T3>::convert(arguments->Get(2));

        (tgt->*functor_)(t1, t2, t3);
    }
};




template <typename T1, typename T2, typename T3, typename T4, typename Functor>
class BasicStaticOperation<void (*)(T1, T2, T3, T4), Functor>: public TypedOperationImpl<void, 4> {
    typedef TypedOperationImpl<void, 4> Base;

    Functor functor_;

public:
    BasicStaticOperation(
            Type *owner,
            const std::string &name,
            const std::string &p0_name,
            const std::string &p1_name,
            const std::string &p2_name,
            const std::string &p3_name,
            Functor functor
    ):
        Base(owner, name, this, true),
        functor_(functor)
    {
        Type* p0_type = TypeFactory<T1>::type();
        Type* p1_type = TypeFactory<T2>::type();
        Type* p2_type = TypeFactory<T3>::type();
        Type* p3_type = TypeFactory<T4>::type();

        Base::AddArgumentType(new ArgumentImpl(p0_name, p0_type));
        Base::AddArgumentType(new ArgumentImpl(p1_name, p1_type));
        Base::AddArgumentType(new ArgumentImpl(p2_name, p2_type));
        Base::AddArgumentType(new ArgumentImpl(p3_name, p3_type));
    }

    virtual void invokeTyped(Typed* target, StaticListOfTyped* arguments) const {
        Base::CheckArgumentTypes(arguments);
        T1 t1 = ParameterTypeHelper<T1>::convert(arguments->Get(0));
        T2 t2 = ParameterTypeHelper<T2>::convert(arguments->Get(1));
        T3 t3 = ParameterTypeHelper<T3>::convert(arguments->Get(2));
        T4 t4 = ParameterTypeHelper<T4>::convert(arguments->Get(3));
        return (*functor_)(t1, t2, t3, t4);
    }
};

template <typename Target, typename T1, typename T2, typename T3, typename T4, typename Functor>
class BasicOperation<void (Target::*)(T1, T2, T3, T4), Functor>: public TypedOperationImpl<void, 4> {
    typedef TypedOperationImpl<void, 4> Base;

    Functor functor_;

public:
    BasicOperation(
            Type *owner,
            const std::string &name,
            const std::string &p0_name,
            const std::string &p1_name,
            const std::string &p2_name,
            const std::string &p3_name,
            Functor functor
    ):
        Base(owner, name, this),
        functor_(functor)
    {
        Type* p0_type = TypeFactory<T1>::type();
        Type* p1_type = TypeFactory<T2>::type();
        Type* p2_type = TypeFactory<T3>::type();
        Type* p3_type = TypeFactory<T4>::type();

        Base::AddArgumentType(new ArgumentImpl(p0_name, p0_type));
        Base::AddArgumentType(new ArgumentImpl(p1_name, p1_type));
        Base::AddArgumentType(new ArgumentImpl(p2_name, p2_type));
        Base::AddArgumentType(new ArgumentImpl(p3_name, p3_type));
    }

    virtual void invokeTyped(Typed* target, StaticListOfTyped* arguments) const {
        Base::CheckTargetValue(target);
        Base::CheckArgumentTypes(arguments);

        Target* tgt = static_cast<Target*>(target);

        T1 t1 = ParameterTypeHelper<T1>::convert(arguments->Get(0));
        T2 t2 = ParameterTypeHelper<T2>::convert(arguments->Get(1));
        T3 t3 = ParameterTypeHelper<T3>::convert(arguments->Get(2));
        T4 t4 = ParameterTypeHelper<T4>::convert(arguments->Get(3));

        return (tgt->*functor_)(t1, t2, t3, t4);
    }
};


template <typename Target, typename T1, typename T2, typename T3, typename T4, typename T5, typename Functor>
class BasicOperation<void (Target::*)(T1, T2, T3, T4, T5), Functor>: public TypedOperationImpl<void, 5> {
    typedef TypedOperationImpl<void, 5> Base;

    Functor functor_;

public:
    BasicOperation(
            Type *owner,
            const std::string &name,
            const std::string &p0_name,
            const std::string &p1_name,
            const std::string &p2_name,
            const std::string &p3_name,
            const std::string &p4_name,
            Functor functor
    ):
        Base(owner, name, this),
        functor_(functor)
    {
        Type* p0_type = TypeFactory<T1>::type();
        Type* p1_type = TypeFactory<T2>::type();
        Type* p2_type = TypeFactory<T3>::type();
        Type* p3_type = TypeFactory<T4>::type();
        Type* p4_type = TypeFactory<T5>::type();

        Base::AddArgumentType(new ArgumentImpl(p0_name, p0_type));
        Base::AddArgumentType(new ArgumentImpl(p1_name, p1_type));
        Base::AddArgumentType(new ArgumentImpl(p2_name, p2_type));
        Base::AddArgumentType(new ArgumentImpl(p3_name, p3_type));
        Base::AddArgumentType(new ArgumentImpl(p4_name, p4_type));
    }

    virtual void invokeTyped(Typed* target, StaticListOfTyped* arguments) const {
        Base::CheckTargetValue(target);
        Base::CheckArgumentTypes(arguments);

        Target* tgt = static_cast<Target*>(target);

        T1 t1 = ParameterTypeHelper<T1>::convert(arguments->Get(0));
        T2 t2 = ParameterTypeHelper<T2>::convert(arguments->Get(1));
        T3 t3 = ParameterTypeHelper<T3>::convert(arguments->Get(2));
        T4 t4 = ParameterTypeHelper<T4>::convert(arguments->Get(3));
        T5 t5 = ParameterTypeHelper<T4>::convert(arguments->Get(4));

        return (tgt->*functor_)(t1, t2, t3, t4, t5);
    }
};


template <>
struct ParameterTypeHelper<TypedIDValue*> {
    static TypedIDValue* convert(Typed* value) {
        return static_cast<TypedIDValue*>(value);
    }
};

template <>
struct ParameterTypeHelper<ListOfTyped*> {
    static ListOfTyped* convert(Typed* value) {
        return static_cast<ListOfTyped*>(value);
    }
};

template <>
struct ParameterTypeHelper<ListOfTypes*> {
    static ListOfTypes* convert(Typed* value) {
        return static_cast<ListOfTypes*>(value);
    }
};

template <>
struct ParameterTypeHelper<StaticListOfTyped*> {
    static StaticListOfTyped* convert(Typed* value) {
        return static_cast<StaticListOfTyped*>(value);
    }
};

}
}

#undef CUBEFS_SOURCE

#endif
